package com.slowfly.rule.engine.model;

import com.google.common.collect.Maps;
import com.slowfly.rule.engine.constants.IRiskConstants;
import com.slowfly.rule.engine.enums.FeatureTypeEnum;
import com.slowfly.rule.engine.function.Function3;
import lombok.AllArgsConstructor;
import lombok.Data;

import java.util.Map;
import java.util.Objects;

@Data
@AllArgsConstructor
public class Operator {

    private static final Map<String, Function3<Integer, Integer, String, String>> map = Maps.newHashMap();

    static {
        map.put("eq", (id, type, value) -> type1(id, type, " == ", value));
        map.put("not_eq", (id, type, value) -> type1(id, type, " != ", value));
        map.put("gt", (id, type, value) -> type1(id, type, " > ", value));
        map.put("ge", (id, type, value) -> type1(id, type, " >= ", value));
        map.put("lt", (id, type, value) -> type1(id, type, " < ", value));
        map.put("le", (id, type, value) -> type1(id, type, " <= ", value));

        map.put("is_null", (id, type, value) -> type2(id, " == ", "null"));
        map.put("not_null", (id, type, value) -> type2(id, " != ", "null"));
        map.put("is_true", (id, type, value) -> type2(id, " == ", "true"));
        map.put("is_false", (id, type, value) -> type2(id, " == ", "false"));

        map.put("field_eq", (id, type, value) -> type3(id, " == ", value));
        map.put("field_not_eq", (id, type, value) -> type3(id, " != ", value));
        map.put("field_gt", (id, type, value) -> type3(id, " > ", value));
        map.put("field_ge", (id, type, value) -> type3(id, " >= ", value));
        map.put("field_lt", (id, type, value) -> type3(id, " < ", value));
        map.put("field_le", (id, type, value) -> type3(id, " <= ", value));
    }

    public static boolean isField(String operator) {
        return operator.startsWith("field_");
    }

    public static String createScript(Condition condition) {
        Function3<Integer, Integer, String, String> func = map.get(condition.getOperator());
        if (Objects.isNull(func) || Objects.isNull(condition.getFeatureId())) {
            return IRiskConstants.DEFAULT_RULE;
        }
        return func.apply(condition.getFeatureId(), condition.getFeatureType(), condition.getValue());
    }

    private static String type1(Integer id, Integer type, String op, String value) {
        if (FeatureTypeEnum.STRING.getCode().equals(type)) {
            return IRiskConstants.VARIABLE_PREFIX + id + op + String.format("'%s'", value);
        }
        return IRiskConstants.VARIABLE_PREFIX + id + op + value;
    }

    private static String type2(Integer id, String op, String value) {
        return IRiskConstants.VARIABLE_PREFIX + id + op + value;
    }

    private static String type3(Integer id, String op, String value) {
        return IRiskConstants.VARIABLE_PREFIX + id + op + IRiskConstants.VARIABLE_PREFIX + value;
    }
}
